package com.ltedu.system.service.impl;

import com.ltedu.common.contants.Constants;
import com.ltedu.common.enums.ErrorCodeEnum;
import com.ltedu.common.exception.BaseException;
import com.ltedu.system.domain.SysMenuRole;
import com.ltedu.system.domain.SysRole;
import com.ltedu.system.domain.vo.SysMenuRoleVO;
import com.ltedu.system.domain.vo.SysRoleVO;
import com.ltedu.system.mapper.SysRoleMapper;
import com.ltedu.system.service.SysMenuRoleService;
import com.ltedu.system.service.SysRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 角色信息 服务实现类
 * </p>
 *
 * @author Jerry
 * @since 2020-11-27
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Autowired
    private SysMenuRoleService menuRoleService;

    /**
     * 获取用户角色列表
     *
     * @param userId 用户ID
     * @return 选中角色ID列表
     */
    @Override
    public List<Long> selectRoleListByUserId(Long userId) {
        return this.baseMapper.selectRoleListByUserId(userId);
    }

    /**
     * 保存角色
     *
     * @param sysRoleVO
     * @return {@link Boolean}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean save(SysRoleVO sysRoleVO) {
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(sysRoleVO, sysRole);
        sysRole.setGmtCreate(new Date());
        sysRole.setGmtModified(new Date());
        int rows = this.baseMapper.insert(sysRole);
        if (rows ==0 ) {
            throw new BaseException(ErrorCodeEnum.SAVE_ROLE_FAIL);
        }
        return rows > 0;
    }

    /**
     * 更新角色
     *
     * @param sysRoleVO
     * @return {@link Boolean}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(SysRoleVO sysRoleVO) {
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(sysRoleVO, sysRole);
        sysRole.setGmtModified(new Date());
        int rows = this.baseMapper.updateById(sysRole);
        if (rows == 0) {
            throw new BaseException(ErrorCodeEnum.UPDATE_ROLE_FAIL);
        }
        return rows > 0;
    }

    /**
     * 角色授权
     *
     * @param sysMenuRoleVo 系统菜单的角色签证官
     * @return {@link Boolean}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveMenuRole(SysMenuRoleVO sysMenuRoleVo) {
        // 将原有权限置为无效状态
        menuRoleService.removeByRoleId(sysMenuRoleVo.getRoleId());

        // 建立新关系
        List<SysMenuRole> menuRoleList = new ArrayList<>();
        for (Long menuId : sysMenuRoleVo.getMenuId()) {
            SysMenuRole sysMenuRole = new SysMenuRole();
            sysMenuRole.setMenuId(menuId);
            sysMenuRole.setRoleId(sysMenuRoleVo.getRoleId());
            sysMenuRole.setState(Constants.NORMAL);
            sysMenuRole.setGmtCreate(new Date());
            sysMenuRole.setGmtModified(new Date());
            menuRoleList.add(sysMenuRole);
        }

        boolean result = menuRoleService.saveBatch(menuRoleList);
        if (!result) {
            throw new BaseException(ErrorCodeEnum.SAVE_MENU_USER_FAIL);
        }
        return result;
    }

    /**
     * 获取用户角色权限
     *
     * @param userId 用户id
     * @return {@link Set<String>}
     */
    @Override
    public Set<String> RolePermissionByUserId(Long userId) {
        List<SysRole> roleList = this.baseMapper.selectRolePermissionByUserId(userId);
        Set<String> roles = new HashSet<>();
        for (SysRole sysRole : roleList) {
            if (StringUtils.isNotEmpty(sysRole.getRoleKey())) {
                roles.addAll(Arrays.asList(sysRole.getRoleKey().trim().split(",")));
            }
        }
        return roles;
    }

    /**
     * 判断用户是否管理员
     *
     * @param userId 用户id
     * @return boolean
     */
    @Override
    public boolean isAdmin(Long userId) {
        int count = this.baseMapper.selectRoleByAdmin(userId);
        return count > 0;
    }
}
